#include "ps.h"
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "Viewer.h"
#include "GaussianMixtureChart.h"
#include "FunctionAndPointsChart.h"

const int PROBLEM_DIM = 1;
const int NUM_ITERACTIONS = 200;
const int NUM_PARTICLES = 10;
double **limits;

double 
fitness(double *particle, void *data)
{
	int i;
	double x;
	double fitness = 1;

	for (i = 0; i < PROBLEM_DIM; i++)
	{
		x = (double) particle[i];
		fitness *= (x * sin(x));
	}

	return fitness;
}


void
set_data()
{
	limits = (double **) calloc (PROBLEM_DIM, sizeof(double*));
	
	for (int i = 0; i < PROBLEM_DIM; i++)
	{
		limits[i] = (double *) calloc (2, sizeof(double));

		limits[i][0] = -100;
		limits[i][1] = 100;
	}
}


void
free_data()
{
	for (int i = 0; i < PROBLEM_DIM; i++)
		free(limits[i]);

	free(limits);
}


void
test_lib_gaussian()
{
	double mean[1];
	double point[1];
	Viewer viewer;

	GaussianMixtureChart chart1(1, limits);
	GaussianMixtureChart chart2(1, limits);
	FunctionAndPointsChart chart3(1, limits);

	mean[0] = 10.0;
	chart1.AddGaussian(mean, 50.0);

	mean[0] = -30.0;
	chart1.AddGaussian(mean, 70.0);

	mean[0] = 80.0;
	chart2.AddGaussian(mean, 5.0);

	chart3.AddFunction(fitness, NULL);

	for (int i = 0; i < NUM_PARTICLES; i++)
	{
		point[0] = (((double) rand() / (double) RAND_MAX)) * (limits[0][1] - limits[0][0]) + limits[0][0];
		chart3.AddPoint(point, fitness(point, NULL));
	}

	viewer.AddChart(&chart1);
	viewer.AddChart(&chart2);
	viewer.AddChart(&chart3);
	viewer.View();
}


int 
main(int argc, char **argv)
{
	set_data();
	// test_lib_gaussian();

	ProbabilisticSearch optimizer(
		fitness, limits,
		PROBLEM_DIM, NULL,
		NUM_PARTICLES,
		NUM_ITERACTIONS);

	optimizer.Optimize();
	
	printf("Result: %lf Fitness: %lf\n",
		optimizer.GetBestSolution()[0], optimizer.GetBestFitness());

	free_data();
	return 0;
}
